package org.Yiran.timetale_re.client.gui;

import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.components.AbstractWidget;
import net.minecraft.client.gui.narration.NarratedElementType;
import net.minecraft.client.gui.narration.NarrationElementOutput;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.ItemStack;
import org.Yiran.timetale_re.Timetale_re;
import org.Yiran.timetale_re.item.tool.screwdriver.core.ScrewdriverItem;
import org.Yiran.timetale_re.item.tool.screwdriver.core.ScrewdriverModuleItem;
import org.Yiran.timetale_re.item.tool.screwdriver.modules.IModule;
import org.Yiran.timetale_re.item.tool.screwdriver.modules.container.ToolModuleContainer;
import org.Yiran.timetale_re.network.NetworkChannel;
import org.Yiran.timetale_re.network.SCResponsePacket;
import org.jetbrains.annotations.NotNull;

import java.util.List;

/**
 * 螺丝刀模块选择界面
 * 允许玩家从螺丝刀中选择并移除模块
 */
public class ModuleSelectionScreen extends Screen {
    /**
     * GUI纹理资源位置
     */
    private static final ResourceLocation MODULE_SELECTION_GUI = ResourceLocation.fromNamespaceAndPath(Timetale_re.MODID, "textures/gui/module_selection.png");
    
    /**
     * GUI尺寸常量
     */
    private static final int GUI_WIDTH = 176;
    private static final int GUI_HEIGHT = 166;
    
    /**
     * 模块列表显示区域相关常量
     */
    private static final int VIEWPORT_HEIGHT = 110; // 可视区域高度
    private static final int ENTRY_HEIGHT = 24;     // 每个模块条目高度
    private static final int ENTRY_SPACING = 2;     // 模块条目间距

    /**
     * 螺丝刀相关数据
     */
    private final ItemStack screwdriverStack;
    private final ScrewdriverItem screwdriverItem;
    private final List<IModule> modules;
    private final Runnable onCloseCallback;
    
    /**
     * GUI位置和滚动相关变量
     */
    private int leftPos;
    private int topPos;
    private int scrollOffset = 0;
    private int maxScrollOffset = 0;
    private boolean scrolling = false;
    private int scrollBarHeight;

    /**
     * 构造函数，初始化模块选择界面
     *
     * @param screwdriverStack 螺丝刀物品栈
     * @param screwdriverItem  螺丝刀物品实例
     * @param onCloseCallback  关闭界面时的回调函数
     */
    public ModuleSelectionScreen(ItemStack screwdriverStack, ScrewdriverItem screwdriverItem, Runnable onCloseCallback) {
        super(Component.translatable("gui.timetale_re.module_selection.title"));
        this.screwdriverStack = screwdriverStack;
        this.screwdriverItem = screwdriverItem;
        this.onCloseCallback = onCloseCallback;

        // 从螺丝刀物品栈加载模块容器
        ToolModuleContainer container = screwdriverItem.createModuleContainer(screwdriverStack);
        container.loadFromItemStack(screwdriverStack);
        this.modules = container.getModules();

        // 计算最大滚动偏移量
        calculateMaxScrollOffset();
    }

    /**
     * 计算最大滚动偏移量
     */
    private void calculateMaxScrollOffset() {
        if (!this.modules.isEmpty()) {
            int totalHeight = this.modules.size() * (ENTRY_HEIGHT + ENTRY_SPACING);
            this.maxScrollOffset = Math.max(0, totalHeight - VIEWPORT_HEIGHT);
        }
    }

    @Override
    protected void init() {
        super.init();
        // 计算GUI在屏幕上的位置
        calculateGuiPosition();
        
        // 计算滚动条高度
        calculateScrollBarHeight();
        
        // 更新界面控件
        updateWidgets();
    }

    /**
     * 计算GUI在屏幕上的位置，使其居中显示
     */
    private void calculateGuiPosition() {
        this.leftPos = (this.width - GUI_WIDTH) / 2;
        this.topPos = (this.height - GUI_HEIGHT) / 2;
    }

    /**
     * 计算滚动条高度
     */
    private void calculateScrollBarHeight() {
        if (!modules.isEmpty()) {
            int totalEntriesHeight = modules.size() * (ENTRY_HEIGHT + ENTRY_SPACING);
            this.scrollBarHeight = Math.max(15, (int) ((float) VIEWPORT_HEIGHT / totalEntriesHeight * VIEWPORT_HEIGHT));
        } else {
            this.scrollBarHeight = VIEWPORT_HEIGHT;
        }
    }

    /**
     * 更新界面控件
     * 清除现有控件并重新添加模块条目控件
     */
    private void updateWidgets() {
        // 清除现有的控件
        this.clearWidgets();

        int startY = topPos + 20;
        int entryWidth = 150;
        int visibleEntries = Math.min(modules.size(), VIEWPORT_HEIGHT / (ENTRY_HEIGHT + ENTRY_SPACING) + 1);

        for (int i = 0; i < visibleEntries && (scrollOffset / (ENTRY_HEIGHT + ENTRY_SPACING) + i) < modules.size(); i++) {
            int moduleIndex = scrollOffset / (ENTRY_HEIGHT + ENTRY_SPACING) + i;
            if (moduleIndex >= 0 && moduleIndex < modules.size()) {
                IModule module = modules.get(moduleIndex);
                this.addRenderableWidget(new ModuleEntryWidget(
                    leftPos + 13,
                    startY + i * (ENTRY_HEIGHT + ENTRY_SPACING) - (scrollOffset % (ENTRY_HEIGHT + ENTRY_SPACING)),
                    entryWidth,
                    ENTRY_HEIGHT,
                    module,
                    () -> selectModule(moduleIndex)
                ));
            }
        }
    }

    /**
     * 选择并移除指定索引的模块
     *
     * @param index 模块索引
     */
    private void selectModule(int index) {
        if (index >= 0 && index < modules.size()) {
            IModule module = modules.get(index);
            // 发送网络包到服务端处理模块移除
            NetworkChannel.CHANNEL.sendToServer(new SCResponsePacket.RemoveSpecificModulePacket(
                module.getModuleId()));
        }
        onClose();
    }

    @Override
    public void render(@NotNull GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick) {
        this.renderBackground(guiGraphics);
        // 绘制GUI背景
        renderGuiBackground(guiGraphics);

        // 限制渲染区域
        guiGraphics.enableScissor(leftPos + 13, topPos + 20, leftPos + 13 + 150, topPos + 20 + VIEWPORT_HEIGHT);
        super.render(guiGraphics, mouseX, mouseY, partialTick);
        guiGraphics.disableScissor();

        // 绘制标题
        renderTitle(guiGraphics);

        // 绘制滚动条
        renderScrollBar(guiGraphics);
    }

    /**
     * 绘制GUI背景
     *
     * @param guiGraphics GuiGraphics实例
     */
    private void renderGuiBackground(GuiGraphics guiGraphics) {
        guiGraphics.blit(MODULE_SELECTION_GUI, leftPos, topPos, 0, 0, GUI_WIDTH, GUI_HEIGHT);
    }

    /**
     * 绘制界面标题
     *
     * @param guiGraphics GuiGraphics实例
     */
    private void renderTitle(GuiGraphics guiGraphics) {
        guiGraphics.drawCenteredString(this.font, this.title, this.width / 2, topPos + 6, 0x404040);
    }

    /**
     * 绘制滚动条
     *
     * @param guiGraphics GuiGraphics实例
     */
    private void renderScrollBar(GuiGraphics guiGraphics) {
        if (maxScrollOffset > 0) {
            int scrollBarX = leftPos + 165;
            int scrollBarY = topPos + 20;
            // 绘制滚动条背景
            guiGraphics.fill(scrollBarX, scrollBarY, scrollBarX + 6, scrollBarY + VIEWPORT_HEIGHT, 0xFF808080);

            // 绘制滚动条滑块
            int scrollBarPosition = calculateScrollBarPosition();
            guiGraphics.fill(scrollBarX, scrollBarY + scrollBarPosition, scrollBarX + 6, scrollBarY + scrollBarPosition + scrollBarHeight, 0xFFC0C0C0);
        }
    }

    /**
     * 计算滚动条滑块位置
     *
     * @return 滚动条滑块的Y坐标偏移量
     */
    private int calculateScrollBarPosition() {
        return (int) ((float) scrollOffset / maxScrollOffset * (VIEWPORT_HEIGHT - scrollBarHeight));
    }

    @Override
    public boolean mouseScrolled(double mouseX, double mouseY, double deltaY) {
        return handleMouseScroll(mouseX, mouseY, deltaY) || super.mouseScrolled(mouseX, mouseY, deltaY);
    }

    /**
     * 处理鼠标滚轮滚动事件
     *
     * @param mouseX 鼠标X坐标
     * @param mouseY 鼠标Y坐标
     * @param deltaY 滚动方向和距离
     * @return 是否处理了滚动事件
     */
    private boolean handleMouseScroll(double mouseX, double mouseY, double deltaY) {
        if (maxScrollOffset > 0) {
            int oldScrollOffset = scrollOffset;
            scrollOffset = Math.max(0, Math.min(scrollOffset - (int) (deltaY * 10), maxScrollOffset));
            if (scrollOffset != oldScrollOffset) {
                updateWidgets();
                return true;
            }
        }
        return false;
    }

    @Override
    public boolean mouseClicked(double mouseX, double mouseY, int button) {
        return handleScrollBarClick(mouseX, mouseY, button) || super.mouseClicked(mouseX, mouseY, button);
    }

    /**
     * 处理滚动条点击事件
     *
     * @param mouseX 鼠标X坐标
     * @param mouseY 鼠标Y坐标
     * @param button 鼠标按键
     * @return 是否处理了点击事件
     */
    private boolean handleScrollBarClick(double mouseX, double mouseY, int button) {
        if (maxScrollOffset > 0 && button == 0) {
            int scrollBarX = leftPos + 165;
            int scrollBarY = topPos + 20;
            int scrollBarPosition = calculateScrollBarPosition();

            // 检查是否点击了滚动条滑块
            if (isMouseOverScrollBar(mouseX, mouseY, scrollBarX, scrollBarY, scrollBarPosition)) {
                scrolling = true;
                return true;
            }

            // 检查是否点击了滚动条背景
            if (isMouseOverScrollBarBackground(mouseX, mouseY, scrollBarX, scrollBarY)) {
                // 点击滚动条背景，滚动一页
                scrollPage(mouseY, scrollBarY, scrollBarPosition);
                return true;
            }
        }
        return false;
    }

    /**
     * 判断鼠标是否在滚动条滑块上
     *
     * @param mouseX             鼠标X坐标
     * @param mouseY             鼠标Y坐标
     * @param scrollBarX         滚动条X坐标
     * @param scrollBarY         滚动条Y坐标
     * @param scrollBarPosition  滚动条滑块位置
     * @return 鼠标是否在滚动条滑块上
     */
    private boolean isMouseOverScrollBar(double mouseX, double mouseY, int scrollBarX, int scrollBarY, int scrollBarPosition) {
        return mouseX >= scrollBarX && mouseX <= scrollBarX + 6 &&
            mouseY >= scrollBarY + scrollBarPosition && mouseY <= scrollBarY + scrollBarPosition + scrollBarHeight;
    }

    /**
     * 判断鼠标是否在滚动条背景上
     *
     * @param mouseX 鼠标X坐标
     * @param mouseY 鼠标Y坐标
     * @param scrollBarX 滚动条X坐标
     * @param scrollBarY 滚动条Y坐标
     * @return 鼠标是否在滚动条背景上
     */
    private boolean isMouseOverScrollBarBackground(double mouseX, double mouseY, int scrollBarX, int scrollBarY) {
        return mouseX >= scrollBarX && mouseX <= scrollBarX + 6 &&
            mouseY >= scrollBarY && mouseY <= scrollBarY + VIEWPORT_HEIGHT;
    }

    /**
     * 按页滚动
     *
     * @param mouseY 鼠标Y坐标
     * @param scrollBarY 滚动条Y坐标
     * @param scrollBarPosition 滚动条滑块位置
     */
    private void scrollPage(double mouseY, int scrollBarY, int scrollBarPosition) {
        int direction = mouseY < scrollBarY + scrollBarPosition ? -1 : 1;
        int oldScrollOffset = scrollOffset;
        scrollOffset = Math.max(0, Math.min(scrollOffset + direction * VIEWPORT_HEIGHT, maxScrollOffset));
        if (scrollOffset != oldScrollOffset) {
            updateWidgets();
        }
    }

    @Override
    public boolean mouseDragged(double mouseX, double mouseY, int button, double dragX, double dragY) {
        return handleMouseDrag(mouseX, mouseY, button) || super.mouseDragged(mouseX, mouseY, button, dragX, dragY);
    }

    /**
     * 处理鼠标拖拽事件
     *
     * @param mouseX 鼠标X坐标
     * @param mouseY 鼠标Y坐标
     * @param button 鼠标按键
     * @return 是否处理了拖拽事件
     */
    private boolean handleMouseDrag(double mouseX, double mouseY, int button) {
        if (scrolling && maxScrollOffset > 0) {
            int scrollBarY = topPos + 20;
            int relativeY = (int) (mouseY - scrollBarY);
            int newScrollOffset = (int) ((float) relativeY / (VIEWPORT_HEIGHT - scrollBarHeight) * maxScrollOffset);
            scrollOffset = Math.max(0, Math.min(newScrollOffset, maxScrollOffset));
            updateWidgets();
            return true;
        }
        return false;
    }

    @Override
    public boolean mouseReleased(double mouseX, double mouseY, int button) {
        handleMouseRelease(button);
        return super.mouseReleased(mouseX, mouseY, button);
    }

    /**
     * 处理鼠标释放事件
     *
     * @param button 鼠标按键
     */
    private void handleMouseRelease(int button) {
        if (button == 0) {
            scrolling = false;
        }
    }

    @Override
    public void onClose() {
        super.onClose();
        if (onCloseCallback != null) {
            onCloseCallback.run();
        }
    }

    @Override
    public boolean isPauseScreen() {
        return false;
    }

    /**
     * 获取螺丝刀物品栈
     *
     * @return 螺丝刀物品栈
     */
    public ItemStack getScrewdriverStack() {
        return screwdriverStack;
    }

    /**
     * 获取螺丝刀物品实例
     *
     * @return 螺丝刀物品实例
     */
    public ScrewdriverItem getScrewdriverItem() {
        return screwdriverItem;
    }

    /**
     * 自定义模块条目控件
     * 显示单个模块的信息和图标
     */
    class ModuleEntryWidget extends AbstractWidget {
        private final IModule module;
        private final ItemStack moduleItemStack;
        private final Runnable onPress;

        /**
         * 构造函数，创建模块条目控件
         *
         * @param x 控件X坐标
         * @param y 控件Y坐标
         * @param width 控件宽度
         * @param height 控件高度
         * @param module 模块实例
         * @param onPress 点击时的回调函数
         */
        public ModuleEntryWidget(int x, int y, int width, int height, IModule module, Runnable onPress) {
            super(x, y, width, height, module.getDisplayName());
            this.module = module;
            this.onPress = onPress;

            // 获取模块对应的物品栈
            String moduleId = module.getModuleId();
            this.moduleItemStack = getModuleItemStack(moduleId);
        }

        @Override
        public void renderWidget(@NotNull GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick) {
            // 渲染背景
            renderEntryBackground(guiGraphics, mouseX, mouseY);

            // 渲染物品图标
            renderModuleIcon(guiGraphics);

            // 渲染模块名称
            renderModuleName(guiGraphics);
        }

        /**
         * 渲染条目背景
         *
         * @param guiGraphics GuiGraphics实例
         * @param mouseX 鼠标X坐标
         * @param mouseY 鼠标Y坐标
         */
        private void renderEntryBackground(GuiGraphics guiGraphics, int mouseX, int mouseY) {
            RenderSystem.enableBlend();
            guiGraphics.blit(MODULE_SELECTION_GUI, getX(), getY(), 0, 166, width, height);

            // 如果鼠标悬停，渲染高亮效果
            if (isMouseOver(mouseX, mouseY)) {
                guiGraphics.blit(MODULE_SELECTION_GUI, getX(), getY(), 0, 190, width, height);
            }
        }

        /**
         * 渲染模块图标
         *
         * @param guiGraphics GuiGraphics实例
         */
        private void renderModuleIcon(GuiGraphics guiGraphics) {
            if (!moduleItemStack.isEmpty()) {
                guiGraphics.renderItem(moduleItemStack, getX() + 4, getY() + 4);
            }
        }

        /**
         * 渲染模块名称
         *
         * @param guiGraphics GuiGraphics实例
         */
        private void renderModuleName(GuiGraphics guiGraphics) {
            // 根据模块等级设置颜色
            int color = getModuleColor(module);
            String moduleName = getMessage().getString();

            // 计算文本位置
            int[] textPosition = calculateTextPosition(moduleName);
            int textX = textPosition[0];
            int textY = textPosition[1];

            if (minecraft != null) {
                guiGraphics.drawString(
                        minecraft.font,
                        getMessage(),
                        textX,
                        textY,
                        color,
                        false
                );
            }
        }

        /**
         * 计算文本位置，使其在控件中居中显示
         *
         * @param moduleName 模块名称
         * @return 包含文本X和Y坐标的数组
         */
        private int[] calculateTextPosition(String moduleName) {
            // 计算文本宽度
            int textWidth = 0;
            if (minecraft != null) {
                textWidth = minecraft.font.width(moduleName);
            }
            
            int availableWidth = width - 24; // 减去左侧图标区域宽度
            int textX = getX() + 12 + (availableWidth - textWidth) / 2;
            int textY = getY() + (height - 8) / 2;

            // 确保文本不会超出左边界
            if (textX < getX() + 24) {
                textX = getX() + 24;
            }

            // 确保文本不会超出右边界
            if (textX + textWidth > getX() + width) {
                textX = getX() + width - textWidth;
            }
            
            return new int[]{textX, textY};
        }

        @Override
        public void onClick(double mouseX, double mouseY) {
            onPress.run();
        }

        @Override
        protected void updateWidgetNarration(@NotNull NarrationElementOutput narrationElementOutput) {
            // 简单实现，实际项目中可能需要更复杂的叙述支持
            narrationElementOutput.add(NarratedElementType.TITLE, getMessage());
        }

        /**
         * 根据模块获取对应的颜色
         *
         * @param module 模块实例
         * @return 颜色值
         */
        private int getModuleColor(IModule module) {
            if (module instanceof ScrewdriverModuleItem screwdriverModule) {
                return switch (screwdriverModule.getModuleLevel()) {
                    case BASIC -> 0x55FF55; // 绿色
                    case ADVANCED -> 0x5555FF; // 蓝色
                    case ELITE -> 0xFF55FF; // 紫色
                };
            }
            return 0xFFFFFF; // 默认白色
        }

        /**
         * 根据模块ID获取对应的物品栈
         *
         * @param moduleId 模块ID
         * @return 对应的物品栈
         */
        private ItemStack getModuleItemStack(String moduleId) {
            try {
                Class<?> itemsRegisterClass = Class.forName("org.Yiran.timetale_re.item.ItemsRegister");
                java.lang.reflect.Field[] fields = itemsRegisterClass.getFields();

                for (java.lang.reflect.Field field : fields) {
                    if (field.getName().equalsIgnoreCase(moduleId)) {
                        Object obj = field.get(null);
                        if (obj instanceof net.minecraftforge.registries.RegistryObject<?> registryObject) {
                            if (registryObject.isPresent()) {
                                return new ItemStack((net.minecraft.world.level.ItemLike) registryObject.get());
                            }
                        }
                    }
                }
            } catch (Exception ignored) {
            }
            return ItemStack.EMPTY;
        }
    }
}